/**
 * 打印类
 * @param {*} ordersData 需要打印的数据
 * @param {*} typeMap 答应单据的样式控制 
 * 
 * 疑问,已有的全局的共有数据typeMap, pageData需要在函数中间传递吗? 哪一种方式更能方便类使用着重写?
 */
function Print(typeMap, ordersData) {
    //检测数据格式是否正确
    if (!Array.isArray(ordersData)) {
        throw new TypeError("Aguments[1] is a array");
    }
    if (! 'top' in typeMap && 'body' in typeMap && 'footer' in typeMap) {
        throw new Error("Aguments[0] require 3 property named 'top' , 'body' and 'footer'");
    }
    this.typeMap = typeMap;
    this.ordersData = ordersData;
}

/**
 * 用set/get来读取和更改默认属性
 * 因为那些属性默认不可写,不可枚举,属性描述符不可改,所以需要一一设定
 */
Object.defineProperties(Print.prototype, {
    // data property to store data 
    _tableTopInLineSize: {  //表格头部信息一行打印数量
        value: 3,
        writable: true
    },
    _tableRowsSize: {       //每页表格行数量
        value: 6,
        writable: true
    },
    _repeatPrintAmount: {   //联数量(重复打印数量)
        value: 1,
        writable: true
    },
    _isPagination: {        //是否分页
        value: true,
        writable: true
    },
    // accessor property    存取器属性
    tableTopInLineSize: {
        get: function () {
            return this._tableTopInLineSize;
        },
        set: function (value) {
            if (typeof value != 'number') {
                throw new TypeError("tableTopInLineSize is a number!");
            } 
            if(value <= 0 || value >= 100) {
                throw new RangeError("1 <= tableTopInLineSize < 100");
            }
            this._tableTopInLineSize = value;
        },
        enumerable: true,
        configurable: true
    },
    tableRowsSize: {
        get: function () {
            return this._tableRowsSize;
        },
        set: function (value) {
            if (typeof value != 'number') {
                throw new TypeError("tableRowsSize is a number!");
            } 
            if(value <= 0) {
                throw new RangeError("1 <= tableRowsSize");
            }
            this._tableRowsSize = value;
        },
        enumerable: true,
        configurable: true
    },
    repeatPrintAmount: {
        get: function () {
            return this._repeatPrintAmount;
        },
        set: function (value) {
            if (typeof value != 'number') {
                throw new TypeError("repeatPrintAmount is a number!");
            } 
            if(value <= 0) {
                throw new RangeError("1 <= repeatPrintAmount");
            }
            this._repeatPrintAmount = value;
        },
        enumerable: true,
        configurable: true
    },
    isPagination: {
        get: function () {
            return this._isPagination;
        },
        set: function (value) {
            if (typeof value != 'boolean') {
                throw new TypeError("isPagination is a boolean!");
            }
            this._isPagination = value;
        },
        enumerable: true,
        configurable: true
    }
});

/**
 * 整合数据, 字段名称与数据挂钩
 * 重写的意义: 可以给某个位置多加一些信息,如head加一个打印时间
 *      将某些信息改变位置显示,比如后端本来说显示在头部,前端修改,将其显示在尾部
 */
Print.prototype._integrationData = function (typeMap, preOrderData) {
    var orderData = { top: {}, body: {}, footer: {} };
    for (var typeMapItem in typeMap) {
        for (var i in typeMap[typeMapItem]) {
            if (!(i in preOrderData)) {
                preOrderData[i] = new Object();
            }
        }
    }
    for (var type in typeMap) {  //枚举位置
        for (var data in preOrderData) { //枚举数据中属性
            if (Array.isArray(preOrderData[data])) {
                orderData.body['sequence'] = [];
                for (var bodyItem in typeMap.body) {
                    if (bodyItem != 'sequence' && bodyItem != 'data') {
                        orderData.body['sequence'].push(bodyItem);
                    }
                }
                orderData.body['columns'] = preOrderData[data];
            } else if (data in typeMap[type]) {     //如果数据在typeMap中
                var tempLable = typeMap[type][data];
                orderData[type][data] = new Object();
                orderData[type][data].lable = tempLable;
                orderData[type][data].value = preOrderData[data];
                continue;
            }
        }
    }
    if(!orderData.body.sequence) {
        throw TypeError("Aguments[1] is a array, each element in this array require a array contain information.");
    }
    return orderData;
}

/**
 * 生成dom
 */
Print.prototype.getHTML = function () {
    var htmlStr = "";
    //每一个订单
    for (var order = 0; order < this.ordersData.length; order++) {
        try{
            var data = this._integrationData(this.typeMap, this.ordersData[order]);
        } catch (e) {
            throw e;
        }
        // console.log(data);
        var pageLength = this.isPagination
                        ? data.body.columns.length / this.tableRowsSize
                        : 1;
            pageLength = Math.ceil(pageLength);
        //每一页
        for (var page = 0; page < pageLength; page++) {
            //每一联
            for (var repeat = 0; repeat < this.repeatPrintAmount; repeat++) {
                var isLastPage = pageLength * this.repeatPrintAmount == page * repeat - 1;
                try{
                    htmlStr += this._buildTableHead(data.top, isLastPage)
                            + this._buildTableBody(data.body, page)
                            + this._buildTableFooter(data.footer, page, pageLength);
                } catch (e) {
                    throw e;
                }
            }
        }
    }
    return htmlStr;
}

/**
 * 生成单据头部
 */
Print.prototype._buildTableHead = function (data, isLastPage) {
    var tableHeadStr = "";
    if (isLastPage) {
        tableHeadStr += "<div style='clear: both;' class='onePage PageNext'>";
    } else {
        tableHeadStr += "<div style='clear: both;'>";
    }
    //生成标题
    if (data.title) {   //如果有标题
        tableHeadStr += "<h1 align = 'center' style='margin: 0;'>" + data.title.lable + "</h1>";
    }
    //生成表格头部
    tableHeadStr += "<table cellspacing = '6' style='margin-top: 5px;'>"
    var tempTableTopInLineSize = this.tableTopInLineSize;
    tableHeadStr += "<tr>";
    for(var tableTopItem in data) {
        if (JSON.stringify(data[tableTopItem].value) == '{}') {
            continue;
        }
        tempTableTopInLineSize--;
        tableHeadStr += "<th> " + data[tableTopItem].lable + "</th>";
        tableHeadStr += "<td> " + data[tableTopItem].value + "</td>";
        if (tempTableTopInLineSize == 0) {
            tableHeadStr += "</tr>"
            tempTableTopInLineSize = this.tableTopInLineSize;
        }
    }
    tableHeadStr += "</table>"
    return tableHeadStr;
}

/**
 * 生成单据中部表格
 * @param data 数据
 * @param page 第几页
 */
Print.prototype._buildTableBody = function (data, page) {
    var tableBodyStr = "";
    tableBodyStr += "<table style = 'margin-top: 0px; line-height:4px; border-collapse:collapse; ' border='1'>"
    tableBodyStr += "<tr>";
    //thead
    tableBodyStr += "<th>序号</th>";
    for (var tableBodyItem in data) {
        if (!Array.isArray(data[tableBodyItem])) {
            tableBodyStr += "<th>" + data[tableBodyItem].lable + "</th>"
        }
    }
    //tbody
    var rowsSize = this.isPagination ? this.tableRowsSize : data.columns.length;
    var sumAMOUNT = 0;
    var sumPrice = 0;
    //每一行
    for(var row = 0; row < rowsSize; row++) {
        tableBodyStr += "<tr>";
        tableBodyStr += "<td>" + (row + page*rowsSize +1) + "</td>";
        //每一行中每一列
        for(var td = 0; td < data.sequence.length; td++) {
            var tdContent = data.columns[row + page*rowsSize][data.sequence[td]];
            tableBodyStr += "<td>" + tdContent + "</td>";
            //对数量和价格求和
            switch (data.sequence[td]) {
                case "AMOUNT": sumAMOUNT += tdContent; break;
                case "SUM": sumPrice += tdContent; break;
            }
        }
        tableBodyStr += "</tr>";
        //合计栏
        if((row + page*rowsSize +1) == data.columns.length) {
            tableBodyStr += "<tr>"
            tableBodyStr += "<td>合计</td>";
            for(var td = 0; td < data.sequence.length; td++) {
                var sum;
                switch(data.sequence[td])
                {
                    case "AMOUNT" : sum = sumAMOUNT; break;
                    case "SUM" : sum = sumPrice; break;
                    default: sum = "";
                }
                sum = parseFloat(sum).toFixed(1);
                sum = sum =='NaN' ? "" : sum;
                tableBodyStr += "<td>" + sum + "</td>";
            }
            tableBodyStr += "</tr>"
            break;
        }
    }
    tableBodyStr += "</table>";
    return tableBodyStr;
}

/**
 * 生成单据尾部信息
 * @param data 页脚数据
 * @param page 页数
 * @param pageLength 总页数
 */
Print.prototype._buildTableFooter = function (data, page, pageLength) {
    var tableFooterStr = "";
    tableFooterStr += "<div style='width:100%;>";
    for (var tableBottomItem in data) {
        if (tableBottomItem == 'MEMO') {
            tableFooterStr += "<div> <div style='width:20%;'>备注</div>";
            tableFooterStr += "<div style='width:80%;'>" + data.MEMO.value + "</div> </div>";
        }
        else {
            tableFooterStr += "<div style='width:70px; float: left'>"
                + data[tableBottomItem].lable
                + ":</div> <div style='width:170px; float: left; border: 1px solid white;'>"
                + (JSON.stringify( data[tableBottomItem].value) == '{}' ? " " : data[tableBottomItem].value)
                + "</div>";
        }
    }
    tableFooterStr += "<div style='width:30%; float: right;'>第" + (page + 1) + "页 共" + pageLength + "页 </div>";
    tableFooterStr += "</div>";
    tableFooterStr += "</div>";
    return tableFooterStr;
}